package sweet.mvc.core

import javax.servlet.{ GenericServlet, ServletRequest, ServletResponse }
import javax.servlet.http.{ HttpServletRequest, HttpServletResponse }
import scala.collection.mutable
import sweet.helper.{ Logger, JList, JMap }
import sweet.mvc.api._

/** Simple base class to extends from and start working */
abstract class AbstractServlet extends GenericServlet with ServletTypes with Logger {
  protected lazy val ctx = getServletContext
  
  def setCtxAttribute(name: String, obj: AnyRef) = ctx.setAttribute(name, obj)
  
  def getRequiredInitParam(name: String): String = {
    val value = getInitParameter(name)
    if(value == null || value.trim == "")
      throw new Exception("Servlet param "+name+" is required.")       
    value
  }
}

/** The default dispatcher servlet that boostrap a config container
 * and delegate request to a processor. */
class SweetDispatcherServlet extends AbstractServlet {
  import Constants._
  
  protected var sweetConfig: SweetConfig = null
  protected lazy val requestProcessor = sweetConfig.requestProcessor  
  protected val sweetConfigClass = classOf[SweetConfig]
  
  /** Instanciating a config instance from a class object of the user's implementation. */  
  def createSweetConfig(clazz: Class[_]): SweetConfig = {
    if(!sweetConfigClass.isAssignableFrom(clazz))
      throw new IllegalArgumentException(clazz +" is not a sub class of sweet.SweetConfig.")
      
    clazz.newInstance.asInstanceOf[SweetConfig]
  }
  
  /** Boostrap sweet application */
  override def init{
    logger.debug("Initializing dispatcher.")
        
    // Load user config instance.   
    val configClassName = getRequiredInitParam(SWEET_CONFIG_CLASSNAME_INIT_PARAM_KEY)
    logger.debug("Creating SweetConfig instance from class " + configClassName)
    sweetConfig = createSweetConfig(Class.forName(configClassName))
    
    // Inject servlet context object to config
    logger.debug("Injecting sweetConfig.servletContext with this application context.")
    sweetConfig.setServletContext(ctx)
    
    // Run init codes in config instance
    logger.debug("Initializing sweetConfig object " + sweetConfig)
    sweetConfig.init
  
    logger.debug("Dispatcher init completed.")
  }
  
  /** Shutdown Sweet application */
  override def destroy{
    logger.debug("Destroying dispatcher.")
    
    sweetConfig.destroy  
    
    logger.debug("Dispatcher destroy completed.")
  }    
  
  /** Find matching controller and delegate work to it's instances. */
  def service(req: ServletRequest, resp: ServletResponse){
    //need to force a case to HTTP based of req & resp.
    requestProcessor.process(req.asInstanceOf[Req], resp.asInstanceOf[Resp])
  }
}
